#include "astralapi.h"
#include "strapi.h"

/**
 * The astral logo is encoded by run length code.
 *
 * The code is represented as an unsigned char.
 * The high 4 bits is the char code, the low 4 bits is
 * the length of the char.
 *
 * Actually an ascii code is 8 bits, the char can be
 * recovered by the charmap.
 *
 * For the length code
 * 1) if the length code is under 8, it's the actual length of the char
 * 2) otherwise, the low 3 bits is the index of countmap,
 *    the length is placed in countmap.
 *
 * The code itself is maped as a printable char named as a key.
 * The key can recover the code via the keymap.
 */
static char countmap[] = {8, 17, 15, 0};
static char charmap[] = "\012\040\047\050\061\051\054\057\123\134\136\137\140\157\174";
static char keymap[] = "\022\263\030\261\031\026\024\021\161\221\341\032\262\023\061\121\342\041\301\347\325\141\207\245";

unsigned char clogo0[] = "ABCDEDFBGB";
unsigned char clogo1[] = "HIHDHJFKHKLKHKGIHDHJAIHMK";
unsigned char clogo2[] = "IHIDJHJHBHKHKDADHMNMHDHKHKNKHODPHKHJMHJ";
unsigned char clogo3[] = "KADAKIHMQHMQHRMKHIHDSHQHKGJBIAKBI";
unsigned char clogo4[] = "KHKHKHKJMHJKHKDHKHKNKHODKHQHKNTHU";
unsigned char clogo5[] = "JDKHKDIKBIHJMQDKGJMVDQDKNWHX";

static void color_print(const char *str, const char *color, int start, int stop)
{
    char cstr[50];
    strncpy(cstr, str + start, stop - start + 1);
    cstr[stop - start + 1] = '\0';
    kprint("%s%s\033[0m", color, cstr);
}


static void decode_str(const unsigned char *zstr, char *buff)
{
    int ptr = 0;
    for (; *zstr; zstr++)
    {
        unsigned char key = *zstr;
        unsigned char code = keymap[key - 'A'];
        int index = (code & 0xf0) >> 4;
        int count = (code & 0x0f) >> 0;
        char c = charmap[index];
        if (count & 0b1000)
        {
            count = countmap[count & 0b11];
        }
        for (int i = 0; i < count; i++)
        {
            *(buff + ptr) = c;
            ptr++;
        }
        *(buff + ptr) = '\n';
        *(buff + ptr + 1) = 0;
    }
}

static void line_print(const unsigned char *zstr)
{
    char str[53];
    decode_str(zstr, str);
    color_print(str, "\033[0m\033[36m", 0, 7);
    color_print(str, "\033[0m\033[35m", 7, 12);
    color_print(str, "\033[0m\033[34m", 12, 17);
    color_print(str, "\033[0m\033[33m", 17, 23);
    color_print(str, "\033[0m\033[32m", 23, 30);
    color_print(str, "\033[0m\033[31m", 30, 33);
    color_print(str, "\033[0m", 33, 53);
}

void banner()
{
    line_print(clogo0);
    line_print(clogo1);
    line_print(clogo2);
    line_print(clogo3);
    line_print(clogo4);
    line_print(clogo5);
    kprint("Astral version %s\n\n", ASSIGNOFF);
}
/**
 / _ \      | |               | |    / _ \  / __|
/ /_\ \ ___ | |_  _ __   __ _ | |   | (_) | \__ \
|  _  |/ __|| __|| '__| / _` || |    \___/  |___/
| | | |\__ \| |_ | |   | (_| || |   ||||||| ooooo
\_| |_/|___/ \__||_|    \__,_||_|   SSSSSSS ^^^^^
**/